package com.haide.channel.pro.util;


import com.haide.channel.pro.constant.CommonDict;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * 加密工具
 * <p>
 * 1.md5加密
 * 2.DES加密
 * </p>
 *
 * @author : 不良人
 * @version : 1.0.0
 * @date : 2017/11/5
 */
@Slf4j
public class SecurityUtil {

    private SecurityUtil() {
    }

    /**
     * MD5 加密
     *
     * @param str 要加密参数
     * @return 加密后值
     */
    public static String md5DesEncrypt(String str) {

        try {
            MessageDigest md5 = MessageDigest.getInstance(CommonDict.MD5);
            md5.update(str.getBytes(StandardCharsets.UTF_8));
            byte[] digest = md5.digest();
            StringBuilder hexString = new StringBuilder();
            String strTemp;
            for (int i = 0; i < digest.length; i++) {
                strTemp = Integer.toHexString((digest[i] & 0x000000FF) | 0xFFFFFF00).substring(6);
                hexString.append(strTemp);
            }
            return hexString.toString();
        } catch (Exception e) {
            log.error("call MD5加密异常", e);
        }
        return str;
    }


    /**
     * MD5 加密，加盐
     *
     * @param str 要加密参数
     * @return 加密后值
     */
    public static String md5DesEncrypt(String str, String salt) {

        try {
            MessageDigest md5 = MessageDigest.getInstance(CommonDict.MD5);
            md5.update(str.concat(salt).getBytes(StandardCharsets.UTF_8));
            byte[] digest = md5.digest();
            StringBuilder hexString = new StringBuilder();
            String strTemp;
            for (int i = 0; i < digest.length; i++) {
                strTemp = Integer.toHexString((digest[i] & 0x000000FF) | 0xFFFFFF00).substring(6);
                hexString.append(strTemp);
            }
            return hexString.toString();
        } catch (Exception e) {
            log.error("call MD5加密异常", e);
        }
        return str;
    }

    /**
     * DES加密
     *
     * @param source 加密内容
     * @param desKey 加密秘钥
     * @return 加密后值
     * @throws Exception
     */
    public static String desEncrypt(String source, String desKey) throws NoSuchAlgorithmException, InvalidKeyException,
            InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
        // 从原始密匙数据创建DESKeySpec对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(CommonDict.DES);
        SecretKey secureKey = keyFactory.generateSecret(new DESKeySpec(desKey.getBytes(StandardCharsets.UTF_8)));
        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance(CommonDict.DES);
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, secureKey);
        // 现在，获取数据并加密
        byte[] destBytes = cipher.doFinal(source.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexRetSB = new StringBuilder();
        for (byte b : destBytes) {
            String hexString = Integer.toHexString(0x00ff & b);
            hexRetSB.append(hexString.length() == 1 ? 0 : "").append(hexString);
        }
        return hexRetSB.toString();
    }

    /**
     * DES解密
     */
    public static String desDecrypt(String source, String desKey) throws NoSuchAlgorithmException, InvalidKeyException,
            InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
        // 解密数据
        byte[] sourceBytes = new byte[source.length() / 2];
        for (int i = 0; i < sourceBytes.length; i++) {
            sourceBytes[i] = (byte) Integer.parseInt(source.substring(i * 2, i * 2 + 2), 16);
        }
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(CommonDict.DES);
        Cipher cipher = Cipher.getInstance(CommonDict.DES);
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, keyFactory.generateSecret(new DESKeySpec(desKey.getBytes(StandardCharsets.UTF_8))));
        // 现在，获取数据并解密
        byte[] destBytes = cipher.doFinal(sourceBytes);
        return new String(destBytes, StandardCharsets.UTF_8);
    }

    /**
     * 通过Base64加密
     *
     * @param bytes byte[]
     * @return byte[]
     */
    public static byte[] base64Encode(byte[] bytes) {
        byte[] encodeBase64 = null;
        try {
            encodeBase64 = Base64.encodeBase64(bytes);
        } catch (Exception e) {
            log.error("base64加密是错", e);
        }
        return encodeBase64;
    }

    /**
     * 通过Base64加密
     *
     * @param src 需要加密的字符串源
     * @return 加密之后的信息
     */
    public static String base64Encode(String src) {

        try {
            return Base64.encodeBase64String(src.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            log.error("Base64加密异常：", e);
        }
        return "";
    }

    /**
     * 通过Base64解密
     *
     * @param src 需要加密的字符串
     * @return 返回解密之后信息
     */
    public static String base64Decode(String src) {

        return new String(new Base64().decode(src), StandardCharsets.UTF_8);
    }
}
